//
// Created by bjliuyong on 2021/6/15.
//

#include "../../include/gc/mark_compact.h"
#include <map>

MarkCompact::MarkCompact(MemoryChunk *memoryChunk) {
    this->m_mem_chunk = memoryChunk;
}

MarkCompact::~MarkCompact() {
}

void MarkCompact::mark() {
    PRINT("\t 开始执行标记操作\n");
    list<MemoryCell *> *mem_cells = m_mem_chunk->get_used_table();
    list<MemoryCell *>::iterator iterator;
    for (iterator = mem_cells->begin(); iterator != mem_cells->end(); iterator++) {
        MemoryCell *cell = *iterator;
        if (cell->get_size() == 4) {
            m_mem_chunk->get_transfer_table()->push_front(cell);
            //这个要回收调 ，然后将数据移动到新的内存区域
            *iterator = new MemoryCell(*cell);
        }
    }
}

void MarkCompact::clean() {
    PRINT("\t 开始执行清理操作\n");
    list<MemoryCell *> *mem_cells = m_mem_chunk->get_used_table();
    list<MemoryCell *>::iterator iterator;

    bool f = false;
    for (iterator = mem_cells->begin(); iterator != mem_cells->end();) {
        MemoryCell *cell = *iterator;
        if (!cell->get_mark()) {
            //clean
            iterator = m_mem_chunk->get_used_table()->erase(iterator);
            m_mem_chunk->get_available_table()->push_front(new MemoryCell(cell->get_start(), cell->get_size()));
            m_mem_chunk->desc_used_cell_num(cell->get_size());
            delete cell;
            f = true;
        } else {
            iterator++;
        }
    }
    if (!f) {
        ERROR_PRINT("[GC后]没有可回收的内存，无法分配内存，执行Full GC\n");
        exit(1);
    }
}

/*void MarkCompact::memory_compact() {
    PRINT("\t 开始执行内存整理操作\n");

    map<uint, MemoryCell *> m;
    list<MemoryCell *> *available_table = m_mem_chunk->get_available_table();
    for (list<MemoryCell *>::iterator iter = available_table->begin(); iter != available_table->end(); iter++) {
        MemoryCell *cell = *iter;
        m[cell->get_start()] = cell;
    }

    map<uint ,MemoryCell*>::iterator  _end = m.end();
    for (list<MemoryCell *>::iterator iter = available_table->begin(); iter != available_table->end();) {

        MemoryCell *cell = *iter;
        if(_end ==  m.find(cell->get_start())){
            iter = available_table->erase(iter);
            delete cell;
            continue;
        }


        map<uint, MemoryCell *>::iterator m_iter = m.find(cell->get_end());

        if(m_iter == m.end()){
            iter++;
            continue;
        }
        MemoryCell *next = m_iter->second;

        if(NULL != next){
            cell->inc_size(next->get_size());
            cell->set_end(next->get_end());
            m.erase(m_iter);
        } else {
            iter++;
        }
    }
    PRINT("\t 结束内存整理操作\n");
}*/

void MarkCompact::memory_compact() {
    PRINT("\t 开始执行内存整理操作\n");

    map<uint, MemoryCell *> m;
    list<MemoryCell *> *available_table = m_mem_chunk->get_available_table();
    //available_table->sort();
    for (list<MemoryCell *>::iterator iter = available_table->begin(); iter != available_table->end();) {
        MemoryCell *cell = *iter;
        MemoryCell *head = NULL;
        MemoryCell *tail = NULL;

        map<uint, MemoryCell *>::iterator head_iter = m.find(cell->get_start());
        map<uint, MemoryCell *>::iterator tail_iter = m.find(cell->get_end());

        if (head_iter != m.end()) {
            head = head_iter->second;
        }
        if (tail_iter != m.end()) {
            tail = tail_iter->second;
        }

        if (NULL == head && NULL == tail) {
            m[cell->get_start()] = cell;
            m[cell->get_end()] = cell;
            iter++;
            continue;
        }

        if (NULL != head && NULL == tail) {
            head->inc_size(cell->get_size());
            head->set_end(cell->get_end());
            iter = available_table->erase(iter);
            m.erase(cell->get_start());
            m[cell->get_end()] = head;
            delete cell;

        } else if (NULL == head && NULL != tail) {
            tail->inc_size(cell->get_size());
            tail->set_start(cell->get_start());
            iter = available_table->erase(iter);
            m.erase(cell->get_end());
            m[cell->get_start()] = tail;
            delete cell;
        } else {
            head->inc_size(cell->get_size() + tail->get_size());
            head->set_end(tail->get_end());
            iter = available_table->erase(iter);
            m.erase(cell->get_start());
            m.erase(cell->get_end());
            m[cell->get_end()] = head;
            tail->set_size(0);
            delete cell;
        }
        //1-3，5-7，3-5，7-10
    }

    for (list<MemoryCell *>::iterator iter = available_table->begin(); iter != available_table->end();) {
        MemoryCell *cell = *iter;
        if (cell->get_size() == 0) {
            iter = available_table->erase(iter);
            delete cell;
        } else {
            iter++;
        }
    }
    m.clear();
    PRINT("\t 结束内存整理操作\n");
}

void MarkCompact::data_compact() {
    for (list<MemoryCell *>::iterator itr = m_mem_chunk->get_transfer_table()->begin();
         itr != m_mem_chunk->get_transfer_table()->end(); itr++) {
        MemoryCell* transfer_cell = *itr;
        this->m_mem_chunk->malloc_after_gc(transfer_cell);
        this->m_mem_chunk->get_used_table()->push_front(transfer_cell);
        itr = m_mem_chunk->get_transfer_table()->erase(itr);
    }
}

void MarkCompact::run() {
    PRINT("[标记-整理算法]开始运行\n");
    mark();
    clean();
    memory_compact();
    data_compact();
}